package com.irdstudio.efp.edoc.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.irdstudio.basic.framework.core.base.FrameworkService;
import com.irdstudio.basic.framework.core.constant.MonAlrmLvlEnums.MonAlrmLvlEnum;
import com.irdstudio.basic.framework.core.constant.StdZbHandleEnums.StdZbHandleEnum;
import com.irdstudio.basic.framework.core.exception.ESBException;
import com.irdstudio.basic.framework.core.util.*;
import com.irdstudio.efp.edoc.common.ImageBizConstant;
import com.irdstudio.efp.edoc.service.bo.ImageBizDetailVO;
import com.irdstudio.efp.edoc.service.bo.LogErrorInfoVO;
import com.irdstudio.efp.edoc.service.common.OpfFileUtil;
import com.irdstudio.efp.edoc.service.facade.ElectronicSignPolyService;
import com.irdstudio.efp.edoc.service.facade.ImageBizDetailService;
import com.irdstudio.efp.edoc.service.facade.LogErrorInfoService;
import com.irdstudio.efp.edoc.service.facade.SubrogationFileAnalysisService;
import com.irdstudio.efp.esb.common.constant.ElectronicSignatureConstant;
import com.irdstudio.efp.esb.common.constant.ElectronicSignatureEnums;
import com.irdstudio.efp.esb.service.bo.req.dzqz.ReqElectronicSignature3001Bean;
import com.irdstudio.efp.esb.service.bo.req.dzqz.ReqElectronicSignature3201Bean;
import com.irdstudio.efp.esb.service.bo.req.dzqz.ReqElectronicSignature3203Bean;
import com.irdstudio.efp.esb.service.bo.req.dzqz.ReqElectronicSignatureDL01Bean;
import com.irdstudio.efp.esb.service.bo.req.dzqz.info.*;
import com.irdstudio.efp.loan.service.facade.AccLoanService;
import com.irdstudio.efp.loan.service.vo.AccLoanVO;
import com.irdstudio.efp.nls.service.facade.NlsApplyInfoService;
import com.irdstudio.efp.nls.service.vo.NlsApplyInfoVO;
import com.jcraft.jsch.ChannelSftp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 
 * 交互文件服务-权益转让书解析
 * 
 * @author ludayong
 * @since 2019年3月11日 上午11:08:00
 * @version 1.0
 */
@Service("subrogationFileAnalysisService")
public class SubrogationAnalysisServiceImpl implements SubrogationFileAnalysisService, FrameworkService {

	private static Logger logger = LoggerFactory.getLogger(SubrogationAnalysisServiceImpl.class);

	@Value("${gzcb.authaddr}")
	private String authaddr;// 授权地址

	@Value("${sign.subrogation.contr_nm}")
	private String contrNm;// 合同名称

	@Value("${sign.subrogation.sign_kwd1}")
	private String signKwd1;// 签署关键字

	@Value("${sign.signonpgcnt}")
	private String signonpgcnt;// 签名域页数

	@Value("${sign.signposnlbx}")
	private String signposnlbx;// 签名域的左下角x轴坐标值

	@Value("${sign.signposnlby}")
	private String signposnlby;// 签名域的左下角y轴坐标值

	@Value("${sign.signposnrux}")
	private String signposnrux;// 签名域的右上角x轴坐标值

	@Value("${sign.signposnruy}")
	private String signposnruy;// 签名域的右上角y轴坐标值

	@Value("${sign.subrogation.xofstcoordposn}")
	private String xofstcoordposn;// X轴偏移坐标

	@Value("${sign.subrogation.yofstcoordposn}")
	private String yofstcoordposn;// Y轴偏移坐标

	@Value("${sign.signimgwdth}")
	private String signimgwdth;// 签章图片宽度

	@Value("${sign.signimghght}")
	private String signimghght;// 签章图片高度

	@Value("${opf.ms.subrogation.remoteFile}")
	private String remoteFile;// 开放平台上传权益转让书目录

	@Value("${opf.scrtFlag}")
	private String scrtFlag;// 开放平台上传文件目录标识

	@Value("${analysis.subrogationFilePath}")
	private String subrogationFilePath;// 权益转让书解析路径

	@Value("${analysis.archSubrogationFilePath}")
	private String archSubrogationFilePath;// 权益转让书归档路径

	@Value("${file.remoteSubrogationDownPath}")
	private String remoteSubrogationDownPath;// 前置文件服务器：权益转让书下载地址

	@Value("${file.remoteSubrogationBakPath}")
	private String remoteSubrogationBakPath;// 前置文件服务器：权益转让书备份地址

	@Value("${ftp.host}")
	private String host;// 前置文件服务器IP地址

	@Value("${ftp.username}")
	private String username;// 前置文件服务器用户名

	@Value("${ftp.pwd}")
	private String pwd;// 前置文件服务器登录密码

	@Value("${ftp.port}")
	private int port;// 前置文件服务器端口号

	@Value("${analysis.downNum}")
	private int downNum;// 影像文件下载最多个数

	@Autowired
	@Qualifier("imageBizDetailService")
	private ImageBizDetailService imageBizDetailService;// 影像业务文件

	@Autowired
	@Qualifier("accLoanService")
	private AccLoanService accLoanService;// 借据信息

	@Autowired
	@Qualifier("logErrorInfoService")
	private LogErrorInfoService logErrorInfoService;// 异常信息表

	@Autowired
	@Qualifier("nlsApplyInfoService")
	private NlsApplyInfoService nlsApplyInfoService;// 网贷申请基本信息

	@Autowired
	@Qualifier("electronicSignPolyService")
	private ElectronicSignPolyService electronicSignPolyService;// 电子签章聚合服务

    private static final String ZIP_SEPARATOR = "-"; // 分割符

    /**
	 * 
	 * 交互文件服务-权益转让书解析 <br>
	 * 0.1:ludayong:2019年3月11日 上午11:08:12:新增 <br>
	 * 0.2:wanglaisheng:2020年10月10日 上午10:17:12:修改--删除解压失败的或者空的压缩包 <br>
	 * 
	 * @author ludayong
	 * @since 2019年3月11日 上午11:08:12
	 * @date 2019年3月11日 上午11:08:12
	 * @version 0.2
	 */
	@Override
	public synchronized boolean analysisSubrogationFile() throws Exception {
		boolean fileDownRes = downloadFile();// 前置文件服务器下载文件
		long startTime = System.currentTimeMillis();
		logger.info("交互文件服务-权益转让书解析：[" + DateTool.formatDate(new Date(startTime), "yyyy-MM-dd HH:mm:ss") + "]， 处理开始！");
		boolean result = false;
		// 1、解压权益转让书
		File files = new File(subrogationFilePath);// 解析文件
		File[] subrogationFiles = files.listFiles();

		if (files.exists()) {// 文件存在
			if (subrogationFiles.length > 0) {
				for (File subrogationFile : subrogationFiles) {
					if (subrogationFile.getName().endsWith(ZipUtil.EXT)) {// 单笔权益转让书
						try {
							// 1、解压权益转让书
							boolean unZipResult = ZipUtil.unZipAll(new File(subrogationFile.getAbsolutePath()),
									new File(subrogationFile.getAbsolutePath().replace(ZipUtil.EXT, "")), true);
							if (unZipResult) {
								try {
									result = this.handleSubrogationFile(subrogationFile.getAbsolutePath());
								} catch (Exception e) {
									result = false;
									e.printStackTrace();
									logger.error("交互文件服务-权益转让书解析出现异常，异常信息" + e.getMessage());
								}
								if(result){
									break;
								}
							}
							//删除解压失败的或者空的压缩包
							else {
								removeZipFile(subrogationFile.getAbsolutePath());
							}
						} catch (IOException e) {
							result = false;
							e.printStackTrace();
							logger.error("交互文件服务-权益转让书解压出现异常，异常信息" + e.getMessage());
						}
					} else if (subrogationFile.isDirectory()) {
						try {
							result = this.handleSubrogationFile(subrogationFile.getAbsolutePath());
						} catch (Exception e) {
							result = false;
							e.printStackTrace();
							logger.error("交互文件服务-权益转让书解析出现异常，异常信息" + e.getMessage());
						}
						if(result){
							break;
						}
					} else {
						result = true;
					}
				}
			}
		}
		long endTime = System.currentTimeMillis();
		logger.info("交互文件服务-权益转让书解析：[" + DateTool.formatDate(new Date(endTime), "yyyy-MM-dd HH:mm:ss") + "]， 处理结束！");
		logger.info("交互文件服务-权益转让书解析，耗时：[" + (endTime - startTime) / 1000.0 + "]秒！");
		return result;
	}

	/**
	 * 
	 * 交互文件服务-权益转让书解析，校验影像个数，记录异常 <br>
	 * 0.1:ludayong:2019年3月11日 上午11:08:17:新增 <br>
	 * 0.2:wanglaisheng:2020年10月10日 上午10:19:17:调整文件名截取逻辑,并将删除文件、文件夹及压缩包的逻辑往下移，避免未能删除压缩包内只有空文件夹的情况 <br>
	 *
	 * @author ludayong
	 * @since 2019年3月11日 上午11:08:17
	 * @date 2019年3月11日 上午11:08:17
	 * @version 0.2
	 */
	private boolean handleSubrogationFile(String filePath) throws Exception {
		// 处理状态
		List<String> states = new ArrayList<String>();
		states.add(StdZbHandleEnum.PENDING.getEnname());// 未处理
		states.add(StdZbHandleEnum.HANGING.getEnname());// 处理中

		String analysisPath = filePath;
		if (filePath.endsWith(ZipUtil.EXT)) {// 单笔权益转让书
			analysisPath = filePath.replace(ZipUtil.EXT, "");// 解析文件目录
		}
		boolean reslut = false;
		boolean signReslut = false;// 电子签章处理结果
		boolean upOPFReslut = false;// 权益转让书上传互开服务器处理结果
		Map<String, Object> param = new HashMap<String, Object>();

		// 1、交互文件服务-权益转让书解析，校验影像个数，记录异常
		int signNum = 0;
		File files = new File(analysisPath);
		File[] subrogationFiles = files.listFiles();

		if (subrogationFiles.length > 0) {
			for (File subrogatFile : subrogationFiles) {
				if(signNum >= downNum){
					break;
				}
				String polFilePath = subrogatFile.getParent();// 文件路径
				String subrogationAbFilePath = subrogatFile.getAbsolutePath();// 文件路径

				String subrogatFileName = subrogatFile.getName();// 文件名
				String billNo = subrogatFileName.substring(0, subrogatFileName.lastIndexOf("_"));// 借据号

				// 非PDF格式格式权益转让书
				if (!subrogatFileName.endsWith(ImageBizConstant.LOAN_PROTOCOL_SUFFIX)) {
					continue;
				}

//				AccLoanVO accLoanVo = new AccLoanVO();
//				accLoanVo.setBillNo(billNo);
//				AccLoanVO queryAccLoanVO = accLoanService.queryByPk(accLoanVo);// 查询权益转让书信息
//				if (queryAccLoanVO != null) {
					String applySeq = billNo;// 借据号（流水号）
					String currentTime = DateTool.getCurrentDateTime();// 当前时间

					LogErrorInfoVO logErrorInfoVo = new LogErrorInfoVO();
					logErrorInfoVo.setApplySeq(applySeq);// 申请流水号
					logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
					logErrorInfoVo.setState(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);// 未处理
					logErrorInfoVo.setTableName("nls_apply_info");// 相关表
					logErrorInfoVo.setCreateTime(currentTime);// 创建时间
					logErrorInfoVo.setLastModifyTime(currentTime);// 最后修改时间

					int errorNum = logErrorInfoService.countByApplySeqAndStates(applySeq, states);// 错误信息
					if (errorNum > 3) {// 当前申请流水记录累计出现三次异常且未处理，不处理当前申请流水的权益转让书
						continue;
					}

					AccLoanVO accLoanVo = new AccLoanVO();
					accLoanVo.setBillNo(billNo);
					AccLoanVO queryAccLoanVO = accLoanService.queryByPk(accLoanVo);// 查询权益转让书信息
					String remark = "";
					// 网贷申请基本信息
					NlsApplyInfoVO inNlsApplyInfoVO = new NlsApplyInfoVO();
					inNlsApplyInfoVO.setApplySeq(applySeq);
					NlsApplyInfoVO queryNlsApplyInfoVO = Optional.ofNullable(nlsApplyInfoService.queryByPk(inNlsApplyInfoVO)).orElseGet(NlsApplyInfoVO::new);;// 查询网贷申请基本信息
					if(StringUtil.isNullorBank(queryNlsApplyInfoVO.getApplySeq())){
						queryNlsApplyInfoVO.setApplySeq(applySeq);
						remark = "权益转让书关联的网贷申请基本信息为空！";
					}
					if (Objects.isNull(queryAccLoanVO)) {
						remark = "权益转让书关联的借据信息为空！";
					}else if (!"11".equals(queryAccLoanVO.getAccountStatus())) {
						remark = "权益转让书关联的借据的台帐状态非理赔结清！";
					}

					if(!StringUtil.isNullorBank(remark)){
						logger.error(remark);
						// 记录异常信息
						recordLogErrorInfo(applySeq, remark, "acc_loan", MonAlrmLvlEnum.SERIOUS.getEnname());
						continue;
					}

					param.put("nlsApplyInfoVO", queryNlsApplyInfoVO);

					String saveSubrogatFilePath = archSubrogationFilePath + applySeq + File.separator + subrogatFileName;// 实际存放目录

					ImageBizDetailVO imageBizDetailVO = new ImageBizDetailVO();// 影像业务文件
					imageBizDetailVO.setApplySeq(applySeq);// 申请流水号
					imageBizDetailVO.setImageId(UUIDUtil.getUUID());// 影像标识
					imageBizDetailVO.setImageType(ImageBizConstant.IMAGE_TYPE_A07);// 影像类型
					imageBizDetailVO.setFileDesc(ImageBizConstant.FILE_SIGN_SUBROGATION_DESC);// 权益转让书
					imageBizDetailVO.setFileName(subrogatFileName);// 文件名
					imageBizDetailVO.setFilePath(saveSubrogatFilePath);// 文件路径
					// imageBizDetail.setBizStage(bizStage);//所属业务阶段
					imageBizDetailVO.setCreateTime(currentTime);// 创建时间
					imageBizDetailVO.setLastModifyTime(currentTime);// 最近修改时间

					// 3、权益转让书签章
					param.put("applySeq", applySeq);
					param.put("tranCode", ElectronicSignatureConstant.TRAN_CODE_3203);
					param.put("opnFlg", ImageBizConstant.YesNoEnum.NO.VALUE);

					param.put("imageFilePath", subrogatFile.getAbsolutePath());// 权益转让书路径
					param.put("conFilePath", polFilePath + File.separator);// 签章权益转让书存放路径
					param.put("imageFileName", subrogatFileName);// 文件名
					param.put("imageType", ImageBizConstant.IMAGE_TYPE_A07);// 权益转让书

					try {
						param = this.initSignInfo(param);// 电子签章-签章信息初始化处理
					} catch (Exception e) {
						logErrorInfoVo.setErrorMsg(e.getMessage());// 错误信息
						logErrorInfoVo.setRemark(e.getMessage());// 备注
						logErrorInfoVo.setErrorType(MonAlrmLvlEnum.SERIOUS.getEnname());// 错误级别
						logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
						logErrorInfoService.insertLogErrorInfo(logErrorInfoVo);// 记录错误信息
						throw new Exception(e.getMessage(), e);
					}

					// 马上权益转让书回传路径
                    String remotePath = "";
                    try {
                         String subDate = getSubDate(analysisPath);
                         remotePath = remoteFile + subDate + File.separator + subrogatFile.getName();
                    } catch (Exception e) {
                        logErrorInfoVo.setErrorMsg("获取马上权益转让书回传日期出现异常，异常信息：" + e.getMessage());// 错误信息
                        logErrorInfoVo.setRemark("获取马上权益转让书回传日期出现异常，异常信息：" + e.getMessage());// 备注
                        logErrorInfoVo.setErrorType(MonAlrmLvlEnum.SERIOUS.getEnname());// 错误级别
                        logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
                        logErrorInfoService.insertLogErrorInfo(logErrorInfoVo);// 记录错误信息
                        throw new Exception(e.getMessage(), e);
                    }

                    try {
						signReslut = electronicSignPolyService.handleElectronicSignPoly(param);// 电子签章-处理
					} catch (ESBException e) {
						remark = "权益转让书签章失败！";
						logErrorInfoVo.setErrorMsg(remark);// 错误信息
						logErrorInfoVo.setRemark(remark);// 备注
						logErrorInfoVo.setErrorType(MonAlrmLvlEnum.SERIOUS.getEnname());// 错误级别
						logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
						logErrorInfoService.insertLogErrorInfo(logErrorInfoVo);// 记录错误信息
						throw new Exception(e.getMessage(), e);
					}

					if (signReslut) {// 电子签章处理结果
						try {
							List<ImageBizDetailVO> queryImageBizDetailList = imageBizDetailService.queryByCondition(imageBizDetailVO);
							if (queryImageBizDetailList != null && !queryImageBizDetailList.isEmpty()) {
								upOPFReslut = true;
							} else {
								upOPFReslut = OpfFileUtil.uploadFile(subrogatFile.getAbsolutePath(), remotePath, scrtFlag);
								logger.info("权益转让书上传开放平台，目标路径：" + remotePath + "，结果[" + upOPFReslut + "]");
							}
							if (!upOPFReslut) {
								logErrorInfoVo.setErrorMsg("权益转让书上传开放平台出错！");// 错误信息
								logErrorInfoVo.setRemark("权益转让书上传开放平台出错！");// 备注
								logErrorInfoVo.setErrorType(MonAlrmLvlEnum.SERIOUS.getEnname());// 错误级别
								logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
								logErrorInfoService.insertLogErrorInfo(logErrorInfoVo);// 记录错误信息
							}
						} catch (Exception e) {
							logErrorInfoVo.setErrorMsg(e.getMessage());// 错误信息
							logErrorInfoVo.setRemark("权益转让书上传开放平台出错！");// 备注
							logErrorInfoVo.setErrorType(MonAlrmLvlEnum.SERIOUS.getEnname());// 错误级别
							logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
							logErrorInfoService.insertLogErrorInfo(logErrorInfoVo);// 记录错误信息
							throw new Exception(e.getMessage(), e);
						}
					}

					if (upOPFReslut) {
						int currnum = 0;
						logger.info("当前新增/更新影像业务文件数据为:" + JSONObject.toJSONString(imageBizDetailVO));
						List<ImageBizDetailVO> queryImageBizDetailList = imageBizDetailService.queryByCondition(imageBizDetailVO);
						if (queryImageBizDetailList != null && !queryImageBizDetailList.isEmpty()) {
							currnum = imageBizDetailService.updateByCondition(imageBizDetailVO);
						} else {
							currnum = imageBizDetailService.insertImageBizDetail(imageBizDetailVO);
						}
						if(currnum > 0){
							signNum++;
						}
						logger.info("当前新增/更新影像业务文件数据条数为:" + currnum);

						boolean moveResult = ZipUtil.moveFile(subrogationAbFilePath, archSubrogationFilePath + applySeq, subrogatFileName,
								true);// 移动文件
						logger.info("移动文件，目标路径:" + archSubrogationFilePath + applySeq + File.separator + subrogatFileName + "结果["
								+ moveResult + "]");
					}
//				} else {
//					continue;
//				}
			}
			if (signNum > 0) {
				reslut = true;
			}
		}
		//将删除文件、文件夹及压缩包的逻辑往下移，避免未能删除压缩包内只有空文件夹的情况
		if (filePath.endsWith(ZipUtil.EXT)) {
			// 清理解压后的压缩包文件
			removeZipFile(filePath);
		} else {
			String zipFilePath = filePath.replace("\\", "/")+ZipUtil.EXT;
			File file = new File(zipFilePath);
			if (file.exists()) {
				// 清理解压后的压缩包文件
				removeZipFile(zipFilePath);
			}
		}
		File analysisFile = new File(analysisPath);
		File[] analysisFiles = analysisFile.listFiles();
		if (analysisFiles.length == 0) {
			String newPath = filePath.replace("\\", "/");
			File file = new File(newPath);
			if (file.exists()) {
				boolean removeZipResult = ZipUtil.deleteFile(filePath);// 删除文件
				logger.info("删除文件，目标路径:" + filePath + "结果[" + removeZipResult + "]");
			}
			// 路径为文件且不为空则进行删除
			boolean removeResult = ZipUtil.deleteFolder(analysisPath);// 删除空目录
			logger.info("删除空目录，目标路径:" + analysisPath + "结果[" + removeResult + "]");
		}
		return reslut;
	}

	/**
	 * 
	 * 从前置文件服务器下载文件 <br>
	 * 0.1:ludayong:2019年3月11日 上午11:08:27:新增 <br>
	 * 
	 * @author ludayong
	 * @since 2019年3月11日 上午11:08:27
	 * @date 2019年3月11日 上午11:08:27
	 * @version 0.1
	 */
	private boolean downloadFile() throws Exception {
		String currentTime = DateTool.getCurrentDateTime();// 当前时间
		LogErrorInfoVO logErrorInfoVo = new LogErrorInfoVO();
		logErrorInfoVo.setApplySeq(UUIDUtil.getUUID());// 申请流水号
		logErrorInfoVo.setState(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);// 未处理
		logErrorInfoVo.setCreateTime(currentTime);// 创建时间
		logErrorInfoVo.setLastModifyTime(currentTime);// 最后修改时间

		List<String> states = new ArrayList<String>();
		states.add(StdZbHandleEnum.PENDING.getEnname());// 未处理
		states.add(StdZbHandleEnum.HANGING.getEnname());// 处理中
		// 连接前置文件服务器
		SFTPUtil sftpUtil = null;
		boolean fileDownRes = false;// 下载文件是否成功
		int downTotal = 0;
		try {
			// 从前置文件服务器下载文件到本地
			sftpUtil = new SFTPUtil(username, pwd, host, port);
			// 检测解析目录是否有需要解析的文件存在
			Vector<ChannelSftp.LsEntry> files = sftpUtil.ls(remoteSubrogationDownPath);
			Objects.requireNonNull(files);// 文件要存在

			// 按最后修改时间对SFTP服务器文件排序
			files = lsEntrySort(files);

			long handTime = System.currentTimeMillis() - 5 * 60 * 1000;
			for (ChannelSftp.LsEntry file : files) {
				String fileName = file.getFilename();// 下载文件名
				long fileMTime = file.getAttrs().getMTime() * 1000L;
				logger.info("处理时间[" + handTime + "]，文件最后修改时间[" + fileMTime + "]");
				if (".".equals(fileName) || "..".equals(fileName) || ZipUtil.EXT.equals(fileName) || !fileName.endsWith(ZipUtil.EXT)) {
					continue;
				} else if (isMatchesCn(fileName)) {
					int num = logErrorInfoService.countByApplySeqAndStates(fileName, states);// 错误信息
					if (num < 3) {// 当前申请流水记录累计出现三次异常且未处理，不获取当前申请流水的权益转让书
						String remark = "权益转让书命名不规范（包含中文），请检查！";
						logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
						logErrorInfoVo.setErrorMsg(remark);// 错误信息
						logErrorInfoVo.setRemark(remark);// 备注
						logErrorInfoVo.setErrorType(MonAlrmLvlEnum.WARNING.getEnname());// 错误级别
						logErrorInfoService.insertLogErrorInfo(logErrorInfoVo);// 记录错误信息
					}
					continue;
				} else if (downTotal >= 1) {
					break;// 每次下载downNum个文件
				} else {
					try {
						boolean singleFileDownRes = sftpUtil.downFile(sftpUtil, remoteSubrogationDownPath, file.getFilename(),
								subrogationFilePath, file.getFilename(), false);
						logger.info("前置文件服务器下载文件：" + remoteSubrogationDownPath + file.getFilename() + "，结果[" + singleFileDownRes + "]");
						if (singleFileDownRes) {
							downTotal++;// 下载文件数
						}
					} catch (Exception e) {
						e.printStackTrace();
						logger.error("前置文件服务器下载文件出现异常：" + e.getMessage());
					}
				}
			}
			if (downTotal > 0) {// 下载文件数大于0，则解析
				fileDownRes = true;
			}
			logger.info("本次前置文件服务器下载文件数目：[" + downTotal + "]");
		} catch (Exception e) {
			String remark = "前置文件服务器下载文件出现异常！";
			logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
			logErrorInfoVo.setTableName("nls_apply_info");// 表名
			logErrorInfoVo.setErrorMsg(e.getMessage());// 错误信息
			logErrorInfoVo.setRemark(remark);// 备注
			logErrorInfoVo.setErrorType(MonAlrmLvlEnum.SERIOUS.getEnname());// 错误级别
			logErrorInfoService.insertLogErrorInfo(logErrorInfoVo);// 记录错误信息
			logger.error(remark + e.getMessage());
			e.printStackTrace();
		} finally {
			if (sftpUtil != null) {
				sftpUtil.closeSFTP();
			}
		}
		return fileDownRes;
	}

	/**
	 * 
	 * 前置文件服务器移动文件 <br>
	 * 0.1:ludayong:2019年3月11日 上午11:08:32:新增 <br>
	 * 
	 * @author ludayong
	 * @since 2019年3月11日 上午11:08:32
	 * @date 2019年3月11日 上午11:08:32
	 * @version 0.1
	 */
	private boolean renameFile(String oldPath, String fileName, String newPath) throws Exception {
		String currentTime = DateTool.getCurrentDateTime();// 当前时间
		LogErrorInfoVO logErrorInfoVo = new LogErrorInfoVO();
		logErrorInfoVo.setApplySeq(UUIDUtil.getUUID());// 申请流水号
		logErrorInfoVo.setState(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);// 未处理
		logErrorInfoVo.setCreateTime(currentTime);// 创建时间
		logErrorInfoVo.setLastModifyTime(currentTime);// 最后修改时间

		SFTPUtil sftpUtil = null;
		boolean renameRes = false;
		try {
			// 连接前置文件服务器
			sftpUtil = new SFTPUtil(username, pwd, host, port);
			// 从前置文件服务器移动目录
			renameRes = sftpUtil.renameFile(oldPath, fileName, newPath, true, true);
		} catch (Exception e) {
			String remark = "前置文件服务器移动文件出现异常！";
			logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
			logErrorInfoVo.setTableName("nls_apply_info");// 表名
			logErrorInfoVo.setErrorMsg(e.getMessage());// 错误信息
			logErrorInfoVo.setRemark(remark);// 备注
			logErrorInfoVo.setErrorType(MonAlrmLvlEnum.SERIOUS.getEnname());// 错误级别
			logErrorInfoService.insertLogErrorInfo(logErrorInfoVo);// 记录错误信息
			logger.error(remark + e.getMessage());
			e.printStackTrace();
		}
		return renameRes;
	}

	/**
	 * 
	 * 正则匹配文件名字是否为中文 <br>
	 * 0.1:ludayong:2019年3月11日 上午11:08:38:新增 <br>
	 * 
	 * @author ludayong
	 * @since 2019年3月11日 上午11:08:38
	 * @date 2019年3月11日 上午11:08:38
	 * @version 0.1
	 */
	private boolean isMatchesCn(String str) {
		if (null == str)
			return false;
		Pattern p = Pattern.compile("[\\u4e00-\\u9fa5]");
		Matcher m = p.matcher(str);
		if (m.find()) {
			return true;
		}
		return false;
	}

	/**
	 * 
	 * 电子签章-签章信息初始化处理 <br>
	 * 0.1:ludayong:2019年3月11日 上午11:08:38:新增 <br>
	 * 
	 * @author ludayong
	 * @since 2019年3月11日 上午11:08:38
	 * @date 2019年3月11日 上午11:08:38
	 * @version 0.1
	 */
	private Map<String, Object> initSignInfo(Map<String, Object> param) throws ESBException, Exception {
		String reqBodyBean = JSONObject.toJSONString(param);
		String tranCode = (String) param.get("tranCode");// 交易代码（接口代码）
		String opnFlg = (String) param.get("opnFlg");// 开户标识

		ReqElectronicSignature3001Bean req3001Bean = null;// 个人开户3001请求信息
		ReqElectronicSignature3201Bean req3201Bean = null;// 创建合同3201请求信息
		ReqElectronicSignature3203Bean req3203Bean = null;// 上传合同3203请求信息
		ReqElectronicSignatureDL01Bean reqCADL01Bean = null;// 合同下载DL01请求信息

		// 1.转换请求bean
		req3001Bean = JSON.toJavaObject(JSONObject.parseObject(reqBodyBean), ReqElectronicSignature3001Bean.class); // 个人开户3001请求信息
		req3201Bean = JSON.toJavaObject(JSONObject.parseObject(reqBodyBean), ReqElectronicSignature3201Bean.class); // 创建合同3201请求信息
		req3203Bean = JSON.toJavaObject(JSONObject.parseObject(reqBodyBean), ReqElectronicSignature3203Bean.class); // 上传合同3203请求信息
		reqCADL01Bean = JSON.toJavaObject(JSONObject.parseObject(reqBodyBean), ReqElectronicSignatureDL01Bean.class); // 合同下载DL01请求信息

		NlsApplyInfoVO nlsApplyInfoVO = (NlsApplyInfoVO) param.get("nlsApplyInfoVO");// 网贷申请基本信息

		if (ElectronicSignatureEnums.YesNoEnum.YES.VALUE.equals(opnFlg)) {// 需要开户
			ElectronicSignature3001ReqPersonInfo person = new ElectronicSignature3001ReqPersonInfo();
			person.setUsrNm(nlsApplyInfoVO.getCusName());// 客户名称
			person.setCertTp(nlsApplyInfoVO.getCertType());
			person.setCertNo(nlsApplyInfoVO.getCertCode());// 安心签会校验身份证格式
			person.setMblNo(nlsApplyInfoVO.getMobile());// 邮箱与手机号不能同时为空；安心签会校验手机号格式
			person.setCtcAddr(nlsApplyInfoVO.getIndivRsdAddr());// 联系地址
			// 客户平台与安心签协议中，明确的认证方式，例如：线下人工审核；公安部数据联网核查；绑定银行卡实名认证；其他（说明方式）
			person.setAuthMode(ElectronicSignatureConstant.AUTHENTICATION_MODE_02);

			req3001Bean.setPerson(person);
			// 0：发送；1：不发送；默认为0，建议选择发送
			req3001Bean.setSendPswdMsgFlg(ElectronicSignatureEnums.SendEnum.NotSend.VALUE);
			// 0：不校验；1：校验；默认为0
			req3001Bean.setVrfyBankCardInfFlg(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);
		}

		if (ElectronicSignatureConstant.TRAN_CODE_3203.equals(tranCode)) {
			ElectronicSignature3203BaseInfo uploadContract = new ElectronicSignature3203BaseInfo();

			uploadContract.setSignFlg(ElectronicSignatureConstant.IS_SIGN_1);// 签署标志
			uploadContract.setContrTp(ElectronicSignatureConstant.CONTRACT_TYPE_CODE_QT);// 合同类型
			uploadContract.setContrNm(contrNm);// 合同名称

			ElectronicSignature3203SignKeyWord signKeyword = new ElectronicSignature3203SignKeyWord();
			signKeyword.setSignKwd(signKwd1); // 关键字
			signKeyword.setXOfstCoordPosn(xofstcoordposn); // X轴偏移坐标
			signKeyword.setYOfstCoordPosn(yofstcoordposn); // Y轴偏移坐标
			signKeyword.setSignImgWdth(signimgwdth); // 签章图片宽度
			signKeyword.setSignImgHght(signimghght); // 签章图片高度

			uploadContract.setSignKeyword(signKeyword);

			// **************************************************//
			List<ElectronicSignature3203SignPosnInfArry> signPosnInfArry = new ArrayList<ElectronicSignature3203SignPosnInfArry>();// 签名域签章信息
			ElectronicSignature3203SignPosnInfArry signLocation1 = new ElectronicSignature3203SignPosnInfArry();
			signLocation1.setSignOnPgCnt("1"); // 签名域页数
			signLocation1.setSignPosnLBX("85"); // 签名域的左下角X轴坐标值
			signLocation1.setSignPosnLBY("550"); // 签名域的左下角Y轴坐标值
			signLocation1.setSignPosnRUX("140"); // 签名域的右上角X轴坐标值
			signLocation1.setSignPosnRUY("575"); // 签名域的右上角Y轴坐标值

			signPosnInfArry.add(signLocation1);

			uploadContract.setSignPosnInfArry(signPosnInfArry);

			List<ElectronicSignature3203SignInfo> signInfos = new ArrayList<ElectronicSignature3203SignInfo>();// 签署信息
			ElectronicSignature3203SignInfo signInfo1 = new ElectronicSignature3203SignInfo();

			signInfo1.setUsrID(UUIDUtil.getUUID());// 用户ID
			signInfo1.setAuthTm(TimeUtil.getTimeStampByPattern("yyyyMMddHHmmss"));// 授权时间
			signInfo1.setAuthAddr(authaddr);// 授权地点
			signInfo1.setPrjNo(UUIDUtil.getUUID());// 项目编号
			signInfos.add(signInfo1);

			uploadContract.setSignBscInfArry(signInfos);
			// **************************************************//

			req3203Bean.setUploadContract(uploadContract);
		} else if (ElectronicSignatureConstant.TRAN_CODE_3201.equals(tranCode)) {
			ElectronicSignature3201BaseInfo createContract = new ElectronicSignature3201BaseInfo();// 请求包信息

			createContract.setContrTplId(UUIDUtil.getUUID());// 待定
			createContract.setSignFlg(ElectronicSignatureConstant.IS_SIGN_1);// 签署标识
			createContract.setContrNm(contrNm);// 合同名称

			List<ElectronicSignature3201SignInfo> signInfos = new ArrayList<ElectronicSignature3201SignInfo>();// 签署信息
			ElectronicSignature3201SignInfo signInfo1 = new ElectronicSignature3201SignInfo();

			signInfo1.setAuthTm(DateTool.getCurrentDateTimess());// 授权时间
			signInfo1.setAuthAddr(authaddr);// 授权地点
			signInfo1.setSignPosVal("待定");
			signInfo1.setPrjNo(UUIDUtil.getUUID());// 项目编号
			// 0：不代签；1：代签；默认为0。不代签的用户，可自行登录安心签使用自己的数字证书完成协议签署。
			signInfo1.setAgncSignFlg(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);
			// 0：不抄送；1：抄送；默认为0如果抄送则AgncSignFlg项无效
			signInfo1.setCopyFlg(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);

			signInfos.add(signInfo1);
			createContract.setSignBscInfArry(signInfos);

			Map<String, String> flPosInf = new HashMap<String, String>();// 文本域信息
			flPosInf.put("text1", "");
			flPosInf.put("text2", "");

			createContract.setFlPosInf(flPosInf);
			// 0：不保存；1：保存；默认为0
			createContract.setSaveFlPosInfFlg(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);// 文本域信息保存标志

			req3201Bean.setCreateContract(createContract);
		}
		param.put("req3001Bean", req3001Bean);
		param.put("req3201Bean", req3201Bean);
		param.put("req3203Bean", req3203Bean);
		param.put("reqCADL01Bean", reqCADL01Bean);
		return param;
	}

	/**
	 *需求编号：【2020D0115】（马上理赔功能）
	 *问题编号：【2019D0115】（获取权益转让书回传日期）
	 *开发人员：【ludayong】
	 *创建日期：【2019/12/24 16:16】
	 *功能描述：
	 *修改日期：【2019/12/24 16:16】
	 *修改描述：
	 */
    private String getSubDate(String subFilePath) throws Exception{
        // 权益转让书回传日期
        String subDate = null;
        // 权益转让书打包文件名称
        String subZipFileName = null;
        if(!StringUtil.isNullorBank(subFilePath) && subFilePath.indexOf(File.separator) >= 0){
            int index = subFilePath.lastIndexOf(File.separator);
            subZipFileName = subFilePath.substring(index+1,subFilePath.length());
        }
        if(!StringUtil.isNullorBank(subZipFileName) && subZipFileName.indexOf(ZIP_SEPARATOR) >= 0){
            int index = subZipFileName.indexOf(ZIP_SEPARATOR);
            subDate = subZipFileName.substring(0,index);
        }
        if(StringUtil.isNullorBank(subDate)){
			subDate = DateTool.getCurrentDate();
		}
        return subDate;
    }

	/**
	 *需求编号：【2020D0115】（马上理赔功能）
	 *问题编号：【2019D0115】（清理解压后的压缩包文件）
	 *开发人员：【ludayong】
	 *创建日期：【2019/12/24 16:16】
	 *功能描述：
	 *修改日期：【2019/12/24 16:16】
	 *修改描述：
	 */
	private void removeZipFile(String filePath) throws Exception {
		String newPath = filePath.replace("\\", "/");
		String fileName = newPath.substring(newPath.lastIndexOf("/") + 1, newPath.length());
		boolean renameReslut = renameFile(remoteSubrogationDownPath, fileName, remoteSubrogationBakPath);
		logger.info("前置文件服务器移动文件结果，目标路径：" + remoteSubrogationBakPath + fileName + "，结果[" + renameReslut + "]");

		if (!renameReslut) {
			String currentTime = DateTool.getCurrentDateTime();// 当前时间
			String remark = "前置文件服务器移动文件出现异常";
			LogErrorInfoVO logErrorInfoVo = new LogErrorInfoVO();
			logErrorInfoVo.setApplySeq(fileName);// 申请流水号
			logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
			logErrorInfoVo.setErrorMsg(remark);// 错误信息
			logErrorInfoVo.setRemark(remark);// 备注
			logErrorInfoVo.setState(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);// 未处理
			logErrorInfoVo.setCreateTime(currentTime);// 创建时间
			logErrorInfoVo.setLastModifyTime(currentTime);// 最后修改时间
			logErrorInfoVo.setErrorType(MonAlrmLvlEnum.SERIOUS.getEnname());// 错误级别
			logErrorInfoService.insertLogErrorInfo(logErrorInfoVo);// 记录错误信息
		}
		// 删除文件
		boolean removeResult = ZipUtil.deleteFile(filePath);
		logger.info("删除文件，目标路径:" + filePath + "结果[" + removeResult + "]");
	}


	/**
	 *需求编号：【2020D0115】（马上理赔功能）
	 *问题编号：【2019D0115】（按最后修改时间对SFTP服务器文件排序）
	 *开发人员：【ludayong】
	 *创建日期：【2019/12/24 16:16】
	 *功能描述：
	 *修改日期：【2019/12/24 16:16】
	 *修改描述：
	 */
	public static Vector<ChannelSftp.LsEntry> lsEntrySort(Vector<ChannelSftp.LsEntry> lsEntrys) {
		ChannelSftp.LsEntry temp;
		for (int i = 0; i < lsEntrys.size() - 1; i++) {
			for (int j = 0; j < lsEntrys.size() - i - 1; j++) {
				if (lsEntrys.get(j).getAttrs().getMTime() * 1000L > lsEntrys.get(j + 1).getAttrs().getMTime() * 1000L) {
					temp = lsEntrys.get(j);
					lsEntrys.set(j,lsEntrys.get(j + 1));
					lsEntrys.set(j + 1,temp);
				}
			}
		}
		return lsEntrys;
	}

	/**
	 *需求编号：【2020D0115】（马上理赔功能）
	 *问题编号：【2019D0115】（记录异常信息）
	 *开发人员：【ludayong】
	 *创建日期：【2019/12/24 16:16】
	 *功能描述：
	 *修改日期：【2019/12/24 16:16】
	 *修改描述：
	 */
	private void recordLogErrorInfo(String applySeq, String remark, String tableName, String errorType) {
		List<String> states = new ArrayList<String>();
		states.add(StdZbHandleEnum.PENDING.getEnname());// 未处理
		states.add(StdZbHandleEnum.HANGING.getEnname());// 处理中
		String currentTime = DateTool.getCurrentDateTime();// 当前时间
		// 错误信息
		LogErrorInfoVO logErrorInfoVo = new LogErrorInfoVO();
		logErrorInfoVo.setSerno(UUIDUtil.getUUID());// 主键
		logErrorInfoVo.setApplySeq(applySeq);
		logErrorInfoVo.setState(ElectronicSignatureEnums.YesNoEnum.NO.VALUE);// 未处理
		logErrorInfoVo.setCreateTime(currentTime);// 创建时间
		logErrorInfoVo.setLastModifyTime(currentTime);// 最后修改时间
		logErrorInfoVo.setTableName(tableName);// 表名
		logErrorInfoVo.setErrorMsg(remark);// 错误信息
		logErrorInfoVo.setRemark(remark);// 备注
		logErrorInfoVo.setErrorType(errorType);// 错误级别
		int errorNum = logErrorInfoService.countByApplySeqAndStates(applySeq, states);// 错误信息
		if (errorNum < 3) {
			logErrorInfoService.insertLogErrorInfo(logErrorInfoVo);// 记录错误信息
		}
	}
}
